<template>
  <div>
    <el-card style="margin: 20px 0">
      <CategorySelector @changeCategory="changeCategory" :isShowList='isShowList'></CategorySelector>
    </el-card>
    <el-card>
      <!-- 使用v-show的时候不能用template，因为v-show是通过css样式来显示隐藏的，template最终没有DOM节点 -->
      <div v-show="isShowList">
        <el-button
          type="primary"
          icon="el-icon-plus"
          @click="isShowList = false"
          >添加属性</el-button
        >
        <el-table style="width: 100%" border :data="attrList">
          <el-table-column label="序号" width="80" align="center" type="index">
          </el-table-column>
          <el-table-column prop="attrName" label="属性名称" width="150">
          </el-table-column>
          <!-- 因为组件不能直接遍历数组中的数组，会直接变成undefined，所以需要使用slot-scope来获取当前行信息再进行遍历 -->
          <el-table-column label="属性值名称">
            <template slot-scope="{ row }">
              <el-tag
                style="margin-right: 10px"
                type="success"
                v-for="attrValue in row.attrValueList"
                :key="attrValue.id"
                >{{ attrValue.valueName }}</el-tag
              >
            </template>
          </el-table-column>
          <el-table-column label="操作" width="150">
            <template slot-scope="{ row }">
              <HintButton
                size="mini"
                type="primary"
                icon="el-icon-edit"
                title="编辑"
                @click="showAttrForm(row)"
              />
              <el-popconfirm
                :title="`你确定要删除${row.attrName}吗？`"
                @onConfirm="deleteAttr(row)"
              >
                <HintButton
                  slot="reference"
                  size="mini"
                  type="danger"
                  icon="el-icon-delete"
                  title="删除"
                />
              </el-popconfirm>
            </template>
          </el-table-column>
        </el-table>
      </div>
      <div v-show="!isShowList">
        <el-form style="width: 25%" :model="attrForm" label-width="60px">
          <el-form-item label="属性名">
            <el-input
              v-model="attrForm.attrName"
              placeholder="请输入属性名"
            ></el-input>
          </el-form-item>
        </el-form>
        <el-button
          type="primary"
          icon="el-icon-plus"
          :disabled="!attrForm.attrName"
          @click="addAttrValue"
          >添加属性值</el-button
        >
        <el-button @click="cancel">取消</el-button>

        <el-table style="width: 100%" border :data="attrForm.attrValueList">
          <el-table-column type="index" label="序号" width="80" align="center">
          </el-table-column>
          <el-table-column prop="prop" label="属性值名称">
            <template slot-scope="{ row }">
              <el-input
                v-if="row.isEdit"
                ref="editInput"
                v-model="row.valueName"
                placeholder="请输入属性值"
                @blur="toLook(row)"
              ></el-input>
              <div v-else @click="toEdit(row)">{{ row.valueName }}</div>
            </template>
          </el-table-column>
          <el-table-column label="操作">
            <template slot-scope="{ row, $index }">
              <el-popconfirm
                :title="`你确定要删除${row.valueName}吗？`"
                @onConfirm="deleteAttrValue($index)"
              >
                <HintButton
                  slot="reference"
                  size="mini"
                  type="danger"
                  icon="el-icon-delete"
                  title="删除"
                />
              </el-popconfirm>
            </template>
          </el-table-column>
        </el-table>
        <el-button type="primary" @click="save">确定</el-button>
        <el-button @click="cancel">取消</el-button>
      </div>
    </el-card>
  </div>
</template>

<script>
import cloneDeep from "lodash/cloneDeep";
// 创建一个attrForm对象，多次使用的时候可以调用
const resetAttrFrom = () => ({
  attrName: "",
  attrValueList: [
    // {
    //   attrId: 0,
    //   id: 0,
    //   valueName: "string",
    // },
  ],
  categoryId: 0, // 声明当前属性属于哪个分类ID
  categoryLevel: 3, // 声明categoryId是第几级分类
  // id: 0,
});

export default {
  name: "Attr",
  data() {
    return {
      category1Id: "",
      category2Id: "",
      category3Id: "",
      attrList: [],
      isShowList: true,
      attrForm: resetAttrFrom(),
    };
  },
  methods: {
    changeCategory(attr) {
      this.category1Id = attr.category1Id;
      this.category2Id = attr.category2Id;
      this.category3Id = attr.category3Id;
      // 发送请求
      this.getAttrList();
    },
    async getAttrList() {
      const { category1Id, category2Id, category3Id } = this;
      const { data } = await this.$API.attr.getAttrList(
        category1Id,
        category2Id,
        category3Id
      );
      this.attrList = data;
    },
    // 当用户点击的时候添加属性值按钮
    addAttrValue() {
      // 通过给attrValueList插入一个对象，可以让table表格中多一行，实现添加属性的功能
      this.attrForm.attrValueList.push({
        // attrId: this.attrForm.id, // 其实添加功能中不需要这个ID，这是为了修改功能使用的
        valueName: "",
        // 给每个属性的属性值对象添加一个标识isEdit，用于控制编辑模式和展示模式的切换
        isEdit: true,
      });
    },
    // 点击跳转到添加/修改界面
    showAttrForm(row) {
      // console.log(row);
      this.isShowList = false;
      // 只有点击确定按钮才能修改属性值，所以需要进行拷贝
      // 如果不进行拷贝的话只要一更改属性，界面就会跟着更改
      // 由于row内部的结构复杂，不能使用...进行浅拷贝，需要使用深拷贝
      this.attrForm = cloneDeep(row);

      // 由于新增了编辑/展示功能，所以attrList中需要有isEdit
      this.attrForm.attrValueList.forEach((item) => {
        // 如果修改数据中的一个属性值，页面会重新渲染，说明该属性是响应式数据
        // 由于新增的属性不是响应式属性，所以需要通过vm.$set来新增响应式属性
        this.$set(item, "isEdit", false);
      });
    },
    cancel() {
      this.isShowList = true;
    },
    // 用于将属性值名称切换为展示模式
    toLook(row) {
      // console.log('row',row);
      // 如果用户没有输入数据,就不允许进入展示模式
      // 如果用户输入的数据已经存在，也不允许进入展示模式
      const valueName = row.valueName;
      const isRepeat = this.attrForm.attrValueList.some((item) => {
        // 排除当前输入的项
        if (item !== row) {
          return item.valueName === valueName;
        }
      });

      if (isRepeat) {
        this.$message.info("属性值名称已存在，请重新输入");
        // 如果属性值已经存在就不能将isEdit改为false，直接return
        return;
      }

      if (valueName) {
        row.isEdit = false;
      } else {
        // 提示用户
        this.$message.info("属性值名称不能为空");
      }
    },
    // 用于将属性值名称切换为编辑模式
    toEdit(row) {
      row.isEdit = true;
      // 更新视图是异步的，所以需要调用nextTick
      // 如果实现了自动获取焦点的功能，那么页面上永远最多只会存在一个input标签
      // nextTick一定可以得到最新的DOM
      this.$nextTick(() => {
        this.$refs.editInput.focus();
      });
    },
    deleteAttrValue($index) {
      // 使用数组的切割来删除当前项
      this.attrForm.attrValueList.splice($index, 1);
    },
    async save() {
      // 1.收集数据
      // 获取到三级分类的id,以及attrFrom
      const { category3Id, attrForm } = this;

      //2.整理数据结构(满足结构需要)
      // {
      //   "attrName": "string",新增要
      //   "attrValueList": [   新增要
      //     {
      //       "attrId": 0,
      //       "id": 0,
      //       "valueName": "string"新增要
      //     }
      //   ],
      //   "categoryId": 0,     新增要
      //   "categoryLevel": 0,     新增要
      //   "id": 0
      // }

      // 2.1 将三级分类id存入attrFrom中
      attrForm.categoryId = category3Id;

      // 2.2 如果没有属性名称，不发送请求
      if (!attrForm.attrName) {
        this.$message.info("属性名称不能为空，保存失败！");
        return;
      }

      // 2.3如果没有属性值，也不能发送请求
      if (!attrForm.attrValueList.length === 0) {
        this.$message.info("至少需要一个属性值，保存失败！");
        return;
      }

      // 2.4清除属性值中多余的isEdit属性
      attrForm.attrValueList.forEach((item) => {
        delete item.isEdit;
      });

      try {
        // 3.发送请求
        await this.$API.attr.addOrUpdate(attrForm);

        // 4.成功之后要做什么

        // 4.1返回列表页
        this.isShowList = true;
        this.$message.success("保存成功！！");

        // 4.2重新请求最新的列表页并展示
        this.getAttrList();

        // 清空添加属性模块的数据，防止再次进入的时候，数据残留
        // this.attrForm = resetAttrFrom();
      } catch (error) {
        this.$message.info("保存失败！！");
      }
    },
    async deleteAttr(row) {
      console.log(row);
      try {
        await this.$API.attr.deleteAttr(row.id);
        this.$message.success("删除成功");
        this.getAttrList();
      } catch (error) {
        this.$message.info("删除失败");
      }
    },
  },
  watch: {
    isShowList(newValue) {
      if (newValue) {
        this.attrForm = resetAttrFrom();
      }
    },
  },
};
</script>

<style>
</style>
